package com.rookie.session.filter.component;

import com.rookie.session.filter.util.CommonUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;

/**
 * @author rookie
 */
@Component
public class GlobalFilter implements Filter {


    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        int time = 1000;
        int times = 5;
        HttpServletRequest request = (HttpServletRequest) servletRequest;
//        将字符串放置到常量池当中，禁止在 JDK 1.8 以下使用
        String ip = CommonUtils.getIp(request).intern();
        if (StringUtils.isNotBlank(ip)) {
            synchronized (ip) {
                Long lockTime = GlobalContainer.IP_LOCK.get(ip);
                if (lockTime != null && System.currentTimeMillis() <= lockTime) {
                    throw new RuntimeException("您正在锁定中");
                }
                if (lockTime != null && System.currentTimeMillis() > lockTime){
                    GlobalContainer.IP_LOCK.remove(ip);
                }
                IpCounter ipCounter = GlobalContainer.IP_MAP.get(ip);
                if (ipCounter == null) {
                    ipCounter = new IpCounter(1, System.currentTimeMillis());
                } else {
                    ipCounter.setCount(ipCounter.getCount() + 1);
                }
                GlobalContainer.IP_MAP.put(ip, ipCounter);
//                惰性清除
                if (System.currentTimeMillis() - ipCounter.getTime() >= time) {
                    GlobalContainer.IP_MAP.remove(ip);
                    ipCounter = new IpCounter(1, System.currentTimeMillis());
                    GlobalContainer.IP_MAP.put(ip, ipCounter);
                }
                if (System.currentTimeMillis() - ipCounter.getTime() < time && ipCounter.getCount() > times) {
                    if (ipCounter.getCount() == times + 1) {
                        Integer num = GlobalContainer.IP_LOCK_TIMES.get(ip);
//                    设置锁定次数
                        if (num != null) {
                            GlobalContainer.IP_LOCK_TIMES.put(ip, ++num);
                        } else {
                            num = 1;
                            GlobalContainer.IP_LOCK_TIMES.put(ip, num);
                        }
                        if (num > 4) {
                            if (lockTime == null) {
                                lockTime = System.currentTimeMillis() + (num - 4) * 10000L;
                            } else {
                                lockTime += (num - 4) * 10000L;
                            }
                            GlobalContainer.IP_LOCK.put(ip, lockTime);
                        }
                    }
                    throw new RuntimeException("访问的太过于频繁");
                }
            }
        }
        filterChain.doFilter(servletRequest, servletResponse);
    }
}
